package com.codrim.cs.data.server.dao.realtime;

import com.codrim.common.utils.bean.BeanUtils;
import com.codrim.common.utils.math.NumberUtils;
import com.codrim.cs.data.rpc.dto.result.OfferDataBase;
import com.codrim.cs.data.rpc.dto.result.RealTimeDataDTO;
import com.codrim.cs.data.server.dao.entity.MergeDayStatCsGeneralDO;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Optional;

import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * 实时数据,dao层与业务层交互实体
 *
 * @author Liang.Zhuge
 * @date 09/08/2017
 */
@Data(staticConstructor = "of")
@NoArgsConstructor
public class RealTimeData {
    private static final Logger logger = LoggerFactory.getLogger(RealTimeData.class);

    private Integer clicks;
    private Integer uClicks;
    private Integer grossConversions;
    private Integer scrubConversions;
    private Integer advId;
    private Integer affId;
    private Integer offerId;

    RealTimeData(RealTimeKey realTimeKey) {
        this.advId = realTimeKey.getAdvId();
        this.affId = realTimeKey.getAffId();
        this.offerId = realTimeKey.getOfferId();
    }

    RealTimeData addClicks(Integer v) {
        this.clicks = NumberUtils.toInt(v) + NumberUtils.toInt(clicks);
        return this;
    }

    RealTimeData addUClicks(Integer v) {
        this.uClicks = NumberUtils.toInt(v) + NumberUtils.toInt(uClicks);
        return this;
    }

    RealTimeData addGrossConversions(Integer v) {
        this.grossConversions = NumberUtils.toInt(v) + NumberUtils.toInt(grossConversions);
        return this;
    }

    RealTimeData addScrubConversions(Integer v) {
        this.scrubConversions = NumberUtils.toInt(v) + NumberUtils.toInt(scrubConversions);
        return this;
    }

    public RealTimeDataDTO toDTO() {
        return BeanUtils.copyProperties(this, RealTimeDataDTO.class);
    }

    /**
     * 将数据累加到`OfferReportDataDTO`上
     *
     * @param reportData 待累加至数据的目标
     */
    public void addToOfferReportData(OfferDataBase reportData, MergeDayStatCsGeneralDO mergeRealTimeBySymbol) {
        final long rOriginClicks = Optional.ofNullable(reportData.getClicks()).orElse(0L);
        final long rOriginUniqueClicks = Optional.ofNullable(reportData.getUniqueClicks()).orElse(0L);
        final long rOriginGrossConversions = Optional.ofNullable(reportData.getGrossConversions()).orElse(0L);
        final long rOriginScrubedConversions = Optional.ofNullable(reportData.getScrubbedConversions()).orElse(0L);
        final long rOriginConversions = Optional.ofNullable(reportData.getConversions()).orElse(0L);
        final float rOriginRevenue = Optional.ofNullable(reportData.getRevenue()).orElse(0f);
        final float rOriginCost = Optional.ofNullable(reportData.getCost()).orElse(0f);

        /*
         * -------分隔------
         * 参数中原始数据都在该注释上方取出,下面不再出现任何取数据的处理,防止取到了累计处理后的数据
         */

        reportData.setClicks(rOriginClicks + NumberUtils.toInt(clicks, 0));
        reportData.setUniqueClicks(rOriginUniqueClicks + NumberUtils.toInt(uClicks, 0));

        final int iGrossConversions = NumberUtils.toInt(grossConversions, 0);
        reportData.setGrossConversions(iGrossConversions + rOriginGrossConversions);
        reportData.setScrubbedConversions(NumberUtils.toInt(scrubConversions, 0)
                + rOriginScrubedConversions);

        final int iConversions = iGrossConversions - NumberUtils.toInt(scrubConversions, 0);
        reportData.setConversions(iConversions + rOriginConversions);

        BigDecimal perRevenue = null;
        BigDecimal perCost = null;
        if (iGrossConversions > 0 && rOriginGrossConversions > 0) {
            perRevenue = new BigDecimal(rOriginRevenue).divide(new BigDecimal(rOriginGrossConversions), 4, RoundingMode.HALF_UP);
            reportData.setRevenue(perRevenue.multiply(new BigDecimal(iGrossConversions)).floatValue()
                    + rOriginRevenue);
        }

        if (iConversions > 0 && rOriginCost > 0) {
            perCost = new BigDecimal(rOriginCost).divide(new BigDecimal(rOriginConversions), 4, RoundingMode.HALF_UP);
            reportData.setCost(perCost.multiply(new BigDecimal(iConversions)).floatValue() + rOriginCost);
        }

        if (mergeRealTimeBySymbol != null) {
            final long rOriginClicksBySymbol = Optional.ofNullable(mergeRealTimeBySymbol.getClicks()).orElse(0L);
            final long rOriginUniqueClicksBySymbol = Optional.ofNullable(mergeRealTimeBySymbol.getUniqueClicks()).orElse(0L);
            final long rOriginGrossConversionsBySymbol = Optional.ofNullable(mergeRealTimeBySymbol.getGrossConversions()).orElse(0L);
            final long rOriginScrubedConversionsBySymbol = Optional.ofNullable(mergeRealTimeBySymbol.getScrubbedConversions()).orElse(0L);
            final long rOriginConversionsBySymbol = Optional.ofNullable(mergeRealTimeBySymbol.getConversions()).orElse(0L);
            final float rOriginRevenueBySymbol = Optional.ofNullable(mergeRealTimeBySymbol.getRevenue()).orElse(0f);
            final float rOriginCostBySymbol = Optional.ofNullable(mergeRealTimeBySymbol.getCost()).orElse(0f);

            mergeRealTimeBySymbol.setClicks(rOriginClicksBySymbol + NumberUtils.toInt(clicks, 0));
            mergeRealTimeBySymbol.setUniqueClicks(rOriginUniqueClicksBySymbol + NumberUtils.toInt(uClicks, 0));
            mergeRealTimeBySymbol.setGrossConversions(iGrossConversions + rOriginGrossConversionsBySymbol);
            mergeRealTimeBySymbol.setScrubbedConversions(NumberUtils.toInt(scrubConversions, 0)
                    + rOriginScrubedConversionsBySymbol);
            mergeRealTimeBySymbol.setConversions(iConversions + rOriginConversionsBySymbol);

            if (reportData.getGrossConversions() > 0 && perRevenue != null) {
                mergeRealTimeBySymbol.setRevenue(perRevenue.multiply(new BigDecimal(iGrossConversions)).floatValue()
                        + rOriginRevenueBySymbol);
            }
            if (rOriginConversions > 0 && perCost != null) {
                mergeRealTimeBySymbol.setCost(perCost.multiply(new BigDecimal(iConversions)).floatValue() + rOriginCostBySymbol);
            }
        }
    }
}
